/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc7_tti_oac.c                                 */
/*  NOTE      =                                                    */
/*  DATE      = 2014/11/20 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>

#include "frcomm.h"

#include "conntrack.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_stmt.h"
#include "../ora_mar_engine.h"
#include "ora_ttc7_tti_oac.h"

/*******************************************************************************
*  FUNC     :  oac
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  i_oac_type                           (数据类型)
*           :  *p_st_stmt                           (Sql_statement)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_tti_oac_unmarshal(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , int i_oac_type
                            , Sql_statement *p_st_stmt)
{
    short s_tmp = 0;
    int i_tmp = 0;
    Ora_metadata st_ora_metadata;
    memset(&st_ora_metadata, 0x00, sizeof(Ora_metadata));

    short s_oacdty = 0;
    short s_oacflg = 0;
    short s_oacpre = 0;
    short s_oacscl = 0;
    int i_oacmxl = 0;
    int i_oacmal = 0;
    int i_oacfl2 = 0;
    int i_oacvsn = 0;
    int i_oaccsi = 0;
    short s_oaccsfrm = 0;
    int i_ttc7_oactoid_old = p_st_sess->i_ttc7_oactoid;
    int i_ttc7_rxhrqsts_old = p_st_sess->i_ttc7_rxhrqsts;

    if (p_st_sess->i_use_special_field == FR_YES && p_st_sess->i_send_typerep == FR_NO)
    {
        ORA_PRINT_DBG("oac skip OCI1\n");
        if (ora_mar_skip(p_st_ora_packet, 1) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oacdty) != FR_SUCC) // oacdty
        goto error;
    ORA_PRINT_DBG("oacdty:[%d]\n", s_oacdty);

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oacflg) != FR_SUCC) // oacflg
        goto error;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oacpre) != FR_SUCC) // oacpre
        goto error;

    if (p_st_sess->i_use_special_field == FR_YES)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oacscl) != FR_SUCC) // oacscl
            goto error;
    }
    else
    {
        if (s_oacdty == ORA_DTY_NUMBER)
        {
            if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // oacscl
                goto error;
            s_oacscl = (short) i_tmp;
        }
        else
        {
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oacscl) != FR_SUCC) // oacscl
                goto error;
        }
    }

    if (s_oacscl > 0 && (s_oacdty == ORA_DTY_TIMESTAMP ||
            s_oacdty == ORA_DTY_TIMESTAMPTZ ||
            s_oacdty == ORA_DTY_TIMESTAMPLTZ ||
            s_oacdty == ORA_DTY_INTERVALDS))
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_oacmxl) != FR_SUCC) // oacmxl
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_oacmal) != FR_SUCC) // oacmal
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_oacfl2) != FR_SUCC) // oacfl2
        goto error;

    switch (s_oacdty)
    {
        case ORA_DTY_NUMBER:
            i_oacmxl = 22;
            break;
        case ORA_DTY_DATE:
            i_oacmxl = 7;
            break;
        case ORA_DTY_TIMESTAMPTZ:
            i_oacmxl = 13;
            break;
        default:
            break;
    }

    if (s_oacdty == ORA_DTY_ROWID2 || s_oacdty == ORA_DTY_UROWID)
        s_oacdty = ORA_DTY_ROWID;

    if (p_st_sess->i_ttc7_oactoid == APM_ORA_FLAG_UNSET)
    {
        if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
            goto error;
        if (s_tmp == 0x00)
        {
            p_st_sess->i_ttc7_oactoid = FR_YES;
            p_st_sess->i_ttc7_rxhrqsts = FR_YES;
        }
        else
        {
            p_st_sess->i_ttc7_oactoid = FR_NO;
            p_st_sess->i_ttc7_rxhrqsts = FR_NO;
        }
    }

    if (p_st_sess->i_ttc7_oactoid == FR_YES) // p_st_sess->s_ora_version >= 8030
    {
        if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC) // oactoid
            goto error;

        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_oacvsn) != FR_SUCC) // oacvsn
            goto error;

        if (p_st_sess->i_use_special_field == FR_YES && p_st_sess->i_send_typerep == FR_NO)
        {
            ORA_PRINT_DBG("oac skip OCI2\n");
            if (ora_mar_skip(p_st_ora_packet, 2) != FR_SUCC)
                goto error;
            if (p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8)
            {
                ORA_PRINT_DBG("oac skip OCI4\n");
                if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                    goto error;
            }
        }

        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_oaccsi) != FR_SUCC) // oaccsi
            goto error;

        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_oaccsfrm) != FR_SUCC) // oaccsfrm
            goto error;

        if (p_st_sess->i_use_special_field == FR_YES)
        {
            ORA_PRINT_DBG("oac skip OCI4\n");
            if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                goto error;

            if (p_st_sess->i_send_typerep == FR_NO)
            {
                ORA_PRINT_DBG("oac skip OCI1\n");
                if (ora_mar_skip(p_st_ora_packet, 1) != FR_SUCC)
                    goto error;
            }

            if (p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8)
            {
                ORA_PRINT_DBG("oac skip OCI4\n");
                if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                    goto error;
            }
        }
    }

    st_ora_metadata.s_oacdty   = s_oacdty;
    st_ora_metadata.s_oacflg   = s_oacflg;
    st_ora_metadata.s_oacpre   = s_oacpre;
    st_ora_metadata.s_oacscl   = s_oacscl;
    st_ora_metadata.i_oacmxl   = i_oacmxl;
    st_ora_metadata.i_oacmal   = i_oacmal;
    st_ora_metadata.i_oacfl2   = i_oacfl2;
    st_ora_metadata.i_oacvsn   = i_oacvsn;
    st_ora_metadata.i_oaccsi   = i_oaccsi;
    st_ora_metadata.s_oaccsfrm = s_oaccsfrm;

    if (i_oac_type == APM_ORA_OACTYPE_DEFINE)
    {
        if (ora_stmt_add_define_metadata(p_st_stmt, st_ora_metadata) != FR_SUCC)
        {
            ORA_PRINT_EMERG("add bind metadata failed\n");
            ORA_FRLOG_ERROR("add bind metadata failed");
            goto error;
        }
    }
    else if (i_oac_type == APM_ORA_OACTYPE_BIND)
    {
        if (ora_stmt_add_bind_metadata(p_st_stmt, st_ora_metadata) != FR_SUCC)
        {
            ORA_PRINT_EMERG("add bind metadata failed\n");
            ORA_FRLOG_ERROR("add bind metadata failed");
            goto error;
        }
    }
    else if (i_oac_type == APM_ORA_OACTYPE_COLUMN)
    {
        if (ora_stmt_add_column_metadata(p_st_stmt, st_ora_metadata) != FR_SUCC)
        {
            ORA_PRINT_EMERG("add column metadata failed\n");
            ORA_FRLOG_ERROR("add column metadata failed");
            goto error;
        }
    }

    ORA_PRINT_ALERT("oacdty:[%d] oacflg:[%d] oacpre:[%d] oacscl:[%d] oacmxl:[%d] oacmal:[%d] oacfl2:[%d] oacvsn:[%d] oaccsi:[%d] oaccsfrm:[%d]\n",
            s_oacdty,
            s_oacflg,
            s_oacpre,
            s_oacscl,
            i_oacmxl,
            i_oacmal,
            i_oacfl2,
            i_oacvsn,
            i_oaccsi,
            s_oaccsfrm);

    return FR_SUCC;
error:
    p_st_sess->i_ttc7_oactoid = i_ttc7_oactoid_old;
    p_st_sess->i_ttc7_rxhrqsts = i_ttc7_rxhrqsts_old;
    return FR_FAIL;
}
